/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aviso.property.controller;

import aviso.entity.Advert;
import aviso.facade.AdvertFacade;
import aviso.helpers.AdvertProperty;
import aviso.property.cache.Cache;
import aviso.property.entity.*;
import aviso.property.entity.Property.PropertyRangeType;
import aviso.property.entity.Property.PropertyType;
import aviso.property.facade.*;
import aviso.property.helpers.PropertyValueCountBase;
import aviso.property.helpers.PropertyValuePair;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 *
 * @author avgusti
 */
@ManagedBean
@SessionScoped
public class PropertyTest implements Serializable {

    /** Creates a new instance of PropertyTest */
    public PropertyTest() {
    }
    @EJB
    AdvertFacade advertFacade;
    @EJB
    ItemFacade itemFacade;
    @EJB
    ItemCategoryFacade categoryFacade;
    @EJB
    PropertyFacade propertyFacade;
    @EJB
    PropertyValueFacade propertyValueFacade;
    @EJB
    PropertyGroupFacade groupFacade;
    @EJB
    PropertiesQueryFacade queryFacade;
    ItemCategory selectedCategory = new ItemCategory();
    List<PropertyValueCountBase> pvc = new ArrayList();
    
    @PostConstruct
    public void init()
    {
        
    }
    
    public Cache getCache() {
        return Cache.getInstance();
    }

    public void setCache(Cache cache) {
    }

    public List<PropertyValueCountBase> getPvc() {
        return pvc;
    }

    public void setPvc(List<PropertyValueCountBase> pvc) {
        this.pvc = pvc;
    }

    public ItemCategory getSelectedCategory() {
        return selectedCategory;
    }

    public void setSelectedCategory(ItemCategory selectedCategory) {
        this.selectedCategory = selectedCategory;
    }

    public void selectCategory(ItemCategory ic) {
        selectedCategory = ic;
    }

    public void addToFilter(PropertyValueCountBase pv) {
        pvc.add(pv);
    }

    public void removeFromFilter(PropertyValueCountBase pv) {
        pvc.remove(pv);
    }

    public void initDB() {
        Map<String, ItemCategory> icl;
        icl = new HashMap<String, ItemCategory>();
        ItemCategory parent, ic;
        parent = ic = createCategory("Property", null);
        icl.put(ic.getName(), ic);
        ic = createCategory("Appartment", parent);
        icl.put(ic.getName(), ic);
        ic = createCategory("House", parent);
        icl.put(ic.getName(), ic);
        ic = new ItemCategory();
        ic = createCategory("Office", parent);
        icl.put(ic.getName(), ic);
        ic = createCategory("Garage", parent);
        icl.put(ic.getName(), ic);

        //property groups

        Map<String, PropertyGroup> pgl = new HashMap<String, PropertyGroup>();
        String groups[] = {"Main", "Extra"};
        for (int i = 0; i < groups.length; i++) {
            PropertyGroup pg = createGroup(groups[i]);
            pgl.put(pg.getName(), pg);
        }

        Map<String, Property> pl = new HashMap<String, Property>();
        Property p = createProperty(AdvertProperty.Address, PropertyType.String, PropertyRangeType.None, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Added_date, PropertyType.Date, PropertyRangeType.Between, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Expire_Date, PropertyType.Date, PropertyRangeType.Between, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Expire_Adv_Date, PropertyType.Date, PropertyRangeType.Between, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Advertised, PropertyType.Bool, PropertyRangeType.None, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Contact, PropertyType.String, PropertyRangeType.None, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Price, PropertyType.Number, PropertyRangeType.Auto, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Total, PropertyType.Number, PropertyRangeType.Auto, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Living, PropertyType.Number, PropertyRangeType.Auto, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Kitchen, PropertyType.Number, PropertyRangeType.Auto, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Balcony, PropertyType.Number, PropertyRangeType.Auto, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Flor, PropertyType.Long, PropertyRangeType.Between, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Flors, PropertyType.Long, PropertyRangeType.Between, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Is_First, PropertyType.Bool, PropertyRangeType.SingleValue, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Is_Last, PropertyType.Bool, PropertyRangeType.SingleValue, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Rooms, PropertyType.Long, PropertyRangeType.MultipleValues, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Is_Merged, PropertyType.Bool, PropertyRangeType.MultipleValues, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.Notes, PropertyType.Text, PropertyRangeType.None, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);
        p = createProperty(AdvertProperty.User_ID, PropertyType.Long, PropertyRangeType.None, pgl.get("Main"), icl.get("Property"));
        pl.put(p.getName(), p);

//
//        Map<String, Item> il = new HashMap<String, Item>();
//        Item i = createItem("Flat1", icl.get("Appartment"));
//        il.put(i.getName(), i);
//        i = createItem("Flat2", icl.get("Appartment"));
//        il.put(i.getName(), i);
//        i = createItem("Flat3", icl.get("Appartment"));
//        il.put(i.getName(), i);
//        i = createItem("Flat4", icl.get("Appartment"));
//        il.put(i.getName(), i);
//
//
//        Map<String, PropertyValue> pvl = new HashMap<String, PropertyValue>();
//        PropertyValue pv = createValue("kiev 1", pl.get("Address"), il.get("Flat1"));
//        pv = createValue("100000", pl.get("Price"), il.get("Flat1"));
//        pv = createValue("50", pl.get("Area"), il.get("Flat1"));
//        pv = createValue("2", pl.get("Rooms"), il.get("Flat1"));
//
//        pv = createValue("kiev 2", pl.get("Address"), il.get("Flat2"));
//        pv = createValue("100000", pl.get("Price"), il.get("Flat2"));
//        pv = createValue("50", pl.get("Area"), il.get("Flat2"));
//        pv = createValue("1", pl.get("Rooms"), il.get("Flat2"));
//
//        pv = createValue("kiev 3", pl.get("Address"), il.get("Flat3"));
//        pv = createValue("100000", pl.get("Price"), il.get("Flat3"));
//        pv = createValue("40", pl.get("Area"), il.get("Flat3"));
//        pv = createValue("1", pl.get("Rooms"), il.get("Flat3"));
//
//        pv = createValue("kiev 4", pl.get("Address"), il.get("Flat4"));
//        pv = createValue("10000", pl.get("Price"), il.get("Flat4"));
//        pv = createValue("45", pl.get("Area"), il.get("Flat4"));
//        pv = createValue("3", pl.get("Rooms"), il.get("Flat4"));
    }

    Property createProperty(String name, PropertyType type, PropertyRangeType range, PropertyGroup group, ItemCategory category) {
        Property p = new Property();
        p.setName(name);
        propertyFacade.create(p);
        p.setGroup(group);
        p.setType(type);
        p.setRange(range);
        p.setCategory(category);
        propertyFacade.edit(p);
        return p;
    }

    PropertyGroup createGroup(String name) {
        PropertyGroup g = new PropertyGroup();
        g.setName(name);
        groupFacade.create(g);
        return g;
    }

    ItemCategory createCategory(String name, ItemCategory parent) {
        ItemCategory ic = new ItemCategory();
        ic.setName(name);
        categoryFacade.create(ic);
        if (parent != null) {
            ic.setParent(parent);
            parent.getChildren().add(ic);
            categoryFacade.edit(ic);
        }
        return ic;
    }

    Item createItem(String name, ItemCategory category) {
        Item i = new Item();
        i.setName(name);
        itemFacade.create(i);
        i.setCategory(category);
        itemFacade.edit(i);
        return i;
    }

    PropertyValue createValue(String value, Property property, Item item) {
        PropertyValue v = new PropertyValue();
        propertyValueFacade.create(v);
        v.setItem(item);
        v.setProperty(property);
        v.setStringvalue(value);
        item.getProperties().put(v.getProperty().getId(), v);
        itemFacade.edit(item);
        propertyValueFacade.edit(v);

        return v;

    }

    public void dropDB() {

        List<PropertyValue> pvs = propertyValueFacade.findAll();
        for (PropertyValue pv : pvs) {
            pv.getItem().getProperties().remove(pv.getProperty().getId());
            itemFacade.edit(pv.getItem());
            propertyValueFacade.remove(pv);
        }

        List<Property> ps = propertyFacade.findAll();
        for (Property p : ps) {
            propertyFacade.remove(p);
        }

        List<PropertyGroup> pgs = groupFacade.findAll();
        for (PropertyGroup pg : pgs) {
            groupFacade.remove(pg);
        }

        List<Item> is = itemFacade.findAll();
        for (Item i : is) {
            itemFacade.remove(i);
        }

        List<ItemCategory> categories = categoryFacade.findAll();
        for (ItemCategory ic : categories) {
            ic.setParent(null);
            ic.getChildren().clear();
        }
//        for (ItemCategory ic : categories) {
//            categoryFacade.edit(ic);
//        }
        for (ItemCategory ic : categories) {
            categoryFacade.remove(ic);
        }



    }

    public void genData() {
    }

    public List<Property> listByCategory(ItemCategory ic) {
        return queryFacade.listPropertiesForCategory(ic);
    }

    public List<Item> listFilteredItems() {
        List<Item> res = queryFacade.listItems(selectedCategory, pvc);
        return res;
    }

    public List<PropertyValuePair> listCountsByCategory(ItemCategory ic) {
        List<Property> pl = queryFacade.listPropertiesForCategory(ic);
        return queryFacade.countPropeties(pl);
    }

    public List<ItemCategory> listCategories() {
        return categoryFacade.findAll();
    }

    public List<Property> listProperties() {
        return propertyFacade.findAll();
    }

    public List<PropertyGroup> listGroups() {
        return groupFacade.findAll();
    }

    public List<PropertyValue> listValues() {
        return null; //propertyValueFacade.findAll();
    }

    public List<Item> listItems() {
        return null; //itemFacade.findAll();
    }
    private long len = 0;

    public long loadIds() {
        if (len == 0) {
            len = queryFacade.loadPropertyValueItemIds(38, "3").length;
        }
        return len;
    }

    public void loadCache() {
        queryFacade.loadCache();
    }

    public void loadCacheFromFile() {
        Cache.loadCacheFromFile();
    }

    public void saveCache() {
        Cache.saveCacheToFile();
    }

    public void updateProperties() {
        int i = 0, page = 10000;
        boolean res;
        do {
            res = queryFacade.saveProperties(i, page, 18L);
            i += 1;
        } while (res);
    }

    private Property createProperty(AdvertProperty advertProperty, PropertyType type, PropertyRangeType range, PropertyGroup group, ItemCategory ic) {
        Property p = new Property();
        p.setName(advertProperty.name);
        p.setId(advertProperty.id);
        //propertyFacade.create(p);
        p.setGroup(group);
        p.setType(type);
        p.setRange(range);
        p.setCategory(ic);
        propertyFacade.edit(p);
        return p;
    }

    public void genItemsFromAdvs() {
        List<Property> ps = propertyFacade.findAll();
        ItemCategory ic = categoryFacade.findRange(new int[]{1, 1}).get(0);
        HashMap<String, Property> pmap = new HashMap();
        for (Property p : ps) {
            pmap.put(p.getName(), p);
        }
        int i = 0, page = 100;
        List<Advert> adverts;
        do {
            adverts = advertFacade.findRange(new int[]{i, page + i});
            for (Advert advert : adverts) {
                Item item = createItem(advert.getAddress(), ic);
                Calendar ce, ca, cn = Calendar.getInstance();
                ce = (Calendar) cn.clone();
                ca = (Calendar) cn.clone();
                ce.add(Calendar.MONTH, 3);
                ca.add(Calendar.MONTH, 1);
                if (advert.getAdded_Date() == null) {
                    advert.setAdded_Date(cn);
                }
                if (advert.getExpire_Date() == null) {
                    advert.setExpire_Date(ce);
                }
                if (advert.getExpire_adv_Date() == null) {
                    advert.setExpire_adv_Date(ca);
                }

                createValue(advert.getAddress(), pmap.get(AdvertProperty.Address.name), item);
                createValue(advert.getContact(), pmap.get(AdvertProperty.Contact.name), item);
                createValue(advert.getNotes(), pmap.get(AdvertProperty.Notes.name), item);
                createValue(advert.getAdded_Date().getTimeInMillis() + "", pmap.get(AdvertProperty.Added_date.name), item);
                createValue(advert.getBalkony_sqr() + "", pmap.get(AdvertProperty.Balcony.name), item);
                createValue(advert.getExpire_Date().getTimeInMillis() + "", pmap.get(AdvertProperty.Expire_Date.name), item);
                createValue(advert.getExpire_adv_Date().getTimeInMillis() + "", pmap.get(AdvertProperty.Expire_Adv_Date.name), item);
                createValue(advert.getFloors() + "", pmap.get(AdvertProperty.Flors.name), item);
                createValue(advert.getKitchen_sqr() + "", pmap.get(AdvertProperty.Kitchen.name), item);
                createValue(advert.getLiving_sqr() + "", pmap.get(AdvertProperty.Living.name), item);
                createValue(advert.getPrice() + "", pmap.get(AdvertProperty.Price.name), item);
                createValue(advert.getRoom_count() + "", pmap.get(AdvertProperty.Rooms.name), item);
                createValue(advert.getTotal_sqr() + "", pmap.get(AdvertProperty.Total.name), item);
                createValue(advert.getUser().getId() + "", pmap.get(AdvertProperty.User_ID.name), item);
            }
            i += page;
            Logger.getAnonymousLogger().log(Level.INFO, "{0}", i);
        } while (adverts.size() > 0);
    }
}
